abstract class Storage{

	protected int capacity;
	protected int stock = 0;
	
	protected Storage(int capacity){
		setCapacity(capacity);
	}
	
	protected Storage(int capacity, int initialStock){
		setCapacity(capacity);
		setStock(initialStock);
	}
	
	private void setCapacity(int capacity){
		this.capacity = capacity;
	}
	
	public int getCapacity(){
		return capacity;
	}
	
	private void setStock(int stock){
		this.stock = stock;
	}
	
	public int getStock(){
		return stock;
	}
	
	// prints a message to the std-output
	protected abstract void message(String msg);
	
	// takes out the amount of product from the storage. if there are not enough items in it, this mehtod waits until there are
	// enough products.
	public synchronized void take(int amount){
		boolean ok = false;
	
		do{
			if(stock >= amount){
				stock -= amount;
				ok = true;
				message("i gave "+amount+" away");
				notifyAll();
			}
			else {
				message("i dont have enough, you have to wait.");
				try{
					wait();
				} catch(Exception e){
					System.out.println("Exception in take (not enough products, wait...): "+e);
				}
			}
		} while(ok == false);
	}
	
	// puts the amount of products into the storage. if there is not enough capacity,
	// the metod waits until the amount fits into the storage
	public synchronized void put(int amount){
		boolean ok = false;
	
		do{
			if(capacity >= (stock+amount)){
				stock += amount;
				ok = true;
				message("i got "+amount);
				notifyAll();
			}
			else {
				try{
					wait();
				} catch(Exception e){
					System.out.println("Exception in put (capacity not enough, wait...): "+e);
				}
			}
		} while(ok == false);
	}
	
	public String toString(){
		return "Eingelagert: "+stock+" (max. "+capacity+")";
	}

}